package IO流;

import org.junit.Test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Random;

/*
    随机存取文件流(RandomAccessFile类)
         RandomAccessFile声明在java.io包下,但直接继承于java.lang.Object类,并且它实现了DataInput、DataOutput这两个接口,所以这个类既可以读也可以写
         RandomAccessFile类支持"随机访问"的方式,程序可以直接跳到文件的任意地方来读、写文件
             支持只访问文件的部分内容
             可以向已存在的文件后追加内容
         RandomAccessFile对象包含一个记录指针,用以标示当前读写处的位置
         当RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建,如果写出到的文件已存在,则会对原有文件内容进行覆盖(默认情况下从头开始依次进行覆盖)
         RandomAccessFile类对象可以自由移动记录指针:
             long getFilePointer():获取文件记录指针的当前位置
             void seek(long pos):将文件记录指针定位到 pos位置

         构造器
             public RandomAccessFile(File file,String mode)
             public RandomAccessFile(String name,String mode)

         创建 RandomAccessFile类实例需要指定一个 mode参数,该参数指定 RandomAccessFile的访问模式:
               r:以只读方式打开
               rw：打开以便读取和写入
               rwd:打开以便读取和写入,同步文件内容的更新
               rws:打开以便读取和写入,同步文件内容和元数据的更新
         如果模式为只读r,则不会创建文件,而是会去读取一个已经存在的文件,如果读取的文件不存在则会出现异常
         如果模式为rw读写,如果文件不存在则会去创建文件,如果存在则不会创建
         每次write数据时,"rw"模式数据不会立即写到硬盘中,而"rwd"模式数据会立即写入硬盘,如果写数据过程发生异常,"rwd"模式中已被write的数据被保存到硬盘,而"rw"则全部丢失

         流的基本应用小结
             流是用来处理数据的
             处理数据时,一定要先明确数据源与数据目的地
                数据源可以是文件,可以是键盘
                数据目的地可以是文件、显示器或者其他设备
             而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理、转换处理等
 */
public class IO09 {

    @Test
    public void test1(){
        RandomAccessFile read = null;
        RandomAccessFile write = null;

        try {
            read = new RandomAccessFile(new File("E:\\FileTest\\成绩合格证明.png"),"r");  //输入
            write = new RandomAccessFile(new File("E:\\FileTest\\copy.png"),"rw"); //输出

            byte[] array = new byte[1024];
            int len;
            while((len = read.read(array)) != -1){
                write.write(array,0,len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (write != null){
                try {
                    write.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (read != null){
                try {
                    read.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Test
    public void test2(){
        RandomAccessFile randomAccessFile = null;
        try {
            randomAccessFile = new RandomAccessFile(new File("E:\\FileTest\\Hello.txt"),"rw");

            //指定开始写入的位置
            randomAccessFile.seek(3); //将指针调到角标为3的位置
            randomAccessFile.write("胡明聪".getBytes());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(randomAccessFile != null){
                try {
                    randomAccessFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //使用RandomAccessFile实现插入效果
    @Test
    public void test3(){
        RandomAccessFile randomAccessFile = null;
        try {
            randomAccessFile = new RandomAccessFile(new File("E:\\FileTest\\Hello.txt"),"rw");

            //指定开始写入的位置
            randomAccessFile.seek(3); //将指针调到角标为3的位置

            //保存指针3后面的所有数据到StringBuilder中
            StringBuilder builder = new StringBuilder((int)new File("E:\\FileTest\\Hello.txt").length()); //直接指定底层数组大小,减少扩容带来的性能损耗
            byte[] array = new byte[20];
            int len;
            while((len = randomAccessFile.read(array)) != -1){
                builder.append(new String(array,0,len));
            }

            //将指定调回 --> 上面的指针已经跑到最后了
            randomAccessFile.seek(3);
            randomAccessFile.write("胡明聪".getBytes());

            //将StringBuilder中的数据写入
            randomAccessFile.write(builder.toString().getBytes());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(randomAccessFile != null){
                try {
                    randomAccessFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
